﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Windows.Controls.Primitives;

namespace SL8.SL.Extensions
{
    public static class FreezingPopupService
    {
        private static Popup currentToolTipPopup;
        private static DispatcherTimer closeTimer;
        private static DispatcherTimer locationTimer;
        private const int closeShowDelay = 800;
        private const int locationShowDelay = 100;


        #region ToolTip提示
        /// <summary>
        /// ToolTip提示
        /// </summary>  
        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.RegisterAttached("Content",
            typeof(FrameworkElement),
            typeof(FreezingPopupService),
            new PropertyMetadata(FreezingPopupService.ToolTipPropertyChangedCallback));

        public static FrameworkElement GetContent(DependencyObject d)
        {
            return (FrameworkElement)d.GetValue(FreezingPopupService.ContentProperty);
        }

        public static void SetContent(DependencyObject d, FrameworkElement value)
        {
            d.SetValue(FreezingPopupService.ContentProperty, value);

            if (d is UIElement && value != null)
            {
                FreezingPopupService.RegisterToolTip((UIElement)d, value);
            }
        }

        private static void ToolTipPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }
        #endregion

        #region 参照控件
        /// <summary>
        /// 参照控件
        /// </summary>  
        public static readonly DependencyProperty PlacementTargetProperty =
            DependencyProperty.RegisterAttached("PlacementTarget",
            typeof(UIElement),
            typeof(FreezingPopupService),
            new PropertyMetadata(FreezingPopupService.PlacementTargetPropertyChangedCallback));

        public static UIElement GetPlacementTarget(DependencyObject d)
        {
            return (UIElement)d.GetValue(FreezingPopupService.PlacementTargetProperty);
        }

        public static void SetPlacementTarget(DependencyObject d, UIElement value)
        {
            d.SetValue(FreezingPopupService.PlacementTargetProperty, value);
        }

        private static void PlacementTargetPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        #endregion

        #region poppup窗口样式
        /// <summary>
        /// poppup窗口样式
        /// </summary>  
        public static readonly DependencyProperty PopupStyleProperty =
            DependencyProperty.RegisterAttached("PopupStyle",
            typeof(Style),
            typeof(FreezingPopupService),
            new PropertyMetadata(FreezingPopupService.PopupStylePropertyChangedCallback));

        public static Style GetPopupStyle(DependencyObject d)
        {
            return (Style)d.GetValue(FreezingPopupService.PopupStyleProperty);
        }

        public static void SetPopupStyle(DependencyObject d, Style value)
        {
            d.SetValue(FreezingPopupService.PopupStyleProperty, value);
        }

        private static void PopupStylePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        #endregion

        #region 位置计算者
        /// <summary>
        /// 位置计算者
        /// </summary>  
        public static readonly DependencyProperty LocationProviderProperty =
            DependencyProperty.RegisterAttached("LocationProvider",
            typeof(IPopupToolTipLocationProvider),
            typeof(FreezingPopupService),
            new PropertyMetadata(FreezingPopupService.LocationProviderPropertyChangedCallback));

        public static IPopupToolTipLocationProvider GetLocationProvider(DependencyObject d)
        {
            return (IPopupToolTipLocationProvider)d.GetValue(FreezingPopupService.LocationProviderProperty);
        }

        public static void SetLocationProvider(DependencyObject d, IPopupToolTipLocationProvider value)
        {
            d.SetValue(FreezingPopupService.LocationProviderProperty, value);
        }

        private static void LocationProviderPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        #endregion

        #region 位置方式
        /// <summary>
        /// 位置方式
        /// </summary>  
        public static readonly DependencyProperty PlacementProperty =
            DependencyProperty.RegisterAttached("Placement",
            typeof(PlacementMode),
            typeof(FreezingPopupService),
            new PropertyMetadata(PlacementMode.ButtonRight, FreezingPopupService.PlacementPropertyChangedCallback));

        public static PlacementMode GetPlacement(DependencyObject d)
        {
            return (PlacementMode)d.GetValue(FreezingPopupService.PlacementProperty);
        }

        public static void SetPlacement(DependencyObject d, PlacementMode value)
        {
            d.SetValue(FreezingPopupService.PlacementProperty, value);
        }

        private static void PlacementPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        #endregion

        private static readonly DependencyProperty ToolTipPopupProperty =
            DependencyProperty.RegisterAttached("ToolTipPopup",
            typeof(Popup),
            typeof(FreezingPopupService), null);

        private static readonly DependencyProperty OwnerProperty =
            DependencyProperty.RegisterAttached("Owner",
            typeof(UIElement),
            typeof(FreezingPopupService), null);

        static FreezingPopupService()
        {
            FreezingPopupService.closeTimer = new DispatcherTimer();
            FreezingPopupService.closeTimer.Interval = new TimeSpan(0, 0, 0, 0, FreezingPopupService.closeShowDelay);
            FreezingPopupService.closeTimer.Tick += new EventHandler(closeTimer_Tick);

            FreezingPopupService.locationTimer = new DispatcherTimer();
            FreezingPopupService.locationTimer.Interval = new TimeSpan(0, 0, 0, 0, FreezingPopupService.locationShowDelay);
            FreezingPopupService.locationTimer.Tick += new EventHandler(locationTimer_Tick);
        }

        static void locationTimer_Tick(object sender, EventArgs e)
        {
            if (FreezingPopupService.currentToolTipPopup == null)
            {
                return;
            }

            Popup popup = FreezingPopupService.currentToolTipPopup;
            UIElement placementTarget = (UIElement)popup.GetValue(FreezingPopupService.PlacementTargetProperty);
            UIElement owner = (UIElement)popup.GetValue(FreezingPopupService.OwnerProperty);

            GeneralTransform tran = placementTarget.TransformToVisual(Application.Current.RootVisual);

            Point point = tran.Transform(new Point(0, 0));

            Rect targetRect = new Rect(point.X, point.Y, ((FrameworkElement)placementTarget).ActualWidth, ((FrameworkElement)placementTarget).ActualHeight);
            Rect popupRect = new Rect();
            if (popup.Child != null)
            {
                tran = popup.Child.TransformToVisual(Application.Current.RootVisual);
                point = tran.Transform(new Point(0, 0));
                popupRect = new Rect(point.X, point.Y, ((FrameworkElement)popup.Child).ActualWidth, ((FrameworkElement)popup.Child).ActualHeight);
            }

            IPopupToolTipLocationProvider provider = FreezingPopupService.GetLocationProvider(owner);
            PlacementMode placement = FreezingPopupService.GetPlacement(owner);

            if (provider == null)
            {
                if (placement == PlacementMode.ButtonRight)
                {
                    provider = new ButtonRightLocationProvider();
                }
                else if (placement == PlacementMode.TopLeft)
                {
                    provider = new TopLeftLocationProvider();
                }
            }

            point = provider.GetLocation(targetRect, popupRect);

            popup.VerticalOffset = point.Y;
            popup.HorizontalOffset = point.X;

            FreezingPopupService.currentToolTipPopup.Child.Opacity = 1;
        }

        private static void closeTimer_Tick(object sender, EventArgs e)
        {
            FreezingPopupService.CloseCurrentToolTipPopup();
        }

        private static void RegisterToolTip(UIElement owner, FrameworkElement content)
        {
            owner.MouseEnter += new MouseEventHandler(FreezingPopupService.OnOwnerMouseEnter);
            owner.MouseLeave += new MouseEventHandler(FreezingPopupService.OnOwnerMouseLeave);
            Popup popup = FreezingPopupService.ConvertToPopup(content);

            Style style = FreezingPopupService.GetPopupStyle(owner);
            if (style != null)
            {
                popup.Style = style;
            }

            UIElement placementTarget = FreezingPopupService.GetPlacementTarget(owner);
            if (placementTarget == null)
            {
                placementTarget = owner;
            }

            popup.SetValue(FreezingPopupService.OwnerProperty, owner);
            popup.SetValue(FreezingPopupService.PlacementTargetProperty, placementTarget);

            owner.SetValue(FreezingPopupService.ToolTipPopupProperty, popup);

            if (popup.Child != null)
            {
                popup.Child.MouseEnter += new MouseEventHandler(PopupMouseEnter);
                popup.Child.MouseLeave += new MouseEventHandler(PopupMouseLeave);
            }

            popup.Opened += new EventHandler(PopupOpened);
            // popup.Child.MouseLeftButtonUp += new MouseButtonEventHandler(Child_MouseLeftButtonUp);
        }

        static void PopupOpened(object sender, EventArgs e)
        {
            FreezingPopupService.locationTimer.Start();
        }

        private static void PopupMouseLeave(object sender, MouseEventArgs e)
        {
            FreezingPopupService.StartCloseTimer();
        }

        private static void PopupMouseEnter(object sender, MouseEventArgs e)
        {
            FreezingPopupService.StopCloseTimer();
        }

        private static void OnOwnerMouseLeave(object sender, MouseEventArgs e)
        {
            FreezingPopupService.StartCloseTimer();
        }

        private static void OnOwnerMouseEnter(object sender, MouseEventArgs e)
        {
            FreezingPopupService.CloseCurrentToolTipPopup();

            UIElement element = (UIElement)sender;
            Popup popup = element.GetValue(FreezingPopupService.ToolTipPopupProperty) as Popup;

            FreezingPopupService.currentToolTipPopup = popup;
            FreezingPopupService.currentToolTipPopup.Child.Opacity = 0.01;
            FreezingPopupService.currentToolTipPopup.IsOpen = true;
        }

        private static void CloseCurrentToolTipPopup()
        {
            FreezingPopupService.closeTimer.Stop();
            if (FreezingPopupService.currentToolTipPopup != null)
            {
                FreezingPopupService.currentToolTipPopup.IsOpen = false;
                FreezingPopupService.currentToolTipPopup = null;
            }
        }

        private static void StartCloseTimer()
        {
            FreezingPopupService.closeTimer.Start();
        }

        private static void StopCloseTimer()
        {
            FreezingPopupService.closeTimer.Stop();
        }

        private static void SetRootVisual()
        {
            //if (FreezingPopupService.rootVisual == null && Application.Current != null)
            //{
            //    FreezingPopupService.rootVisual = (Application.Current.RootVisual as FrameworkElement);
            //    if (FreezingPopupService.rootVisual != null)
            //    {
            //        //FreezingToolTipService._rootVisual.MouseMove += new MouseEventHandler(ToolTipService.OnRootMouseMove);
            //        //FreezingToolTipService._rootVisual.SizeChanged += new SizeChangedEventHandler(ToolTipService.OnRootVisualSizeChanged);
            //    }
            //}
        }

        private static Popup ConvertToPopup(FrameworkElement content)
        {
            Popup popup = new Popup();
            Border border = new Border();
            border.Child = content;
            popup.Child = border;
            return popup;
        }
    }
}
